/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;


/**
 * Server-side class for the player. This class is used to control player-specific behavior 
 * such as color, name, inventory and towers.
 */
@SuppressWarnings("serial")
public class Player extends UnicastRemoteObject implements IPlayer, IRmiPlayer {
	
	
	/**
	 * Game board
	 */
	private IGameBoard gameBoard;
	
	
	/**
	 * Displayed name of player
	 */
	private String name = "";
	
	
	/**
	 * In-game color of player
	 */
	private int color = 0;
	
	
	/**
	 * If player is ready to start a new game
	 */
	private boolean ready = false;
	
	
	/**
	 * Prestige points
	 */
	private int points;
	
	
	/**
	 * Money
	 */
	private int money = 0;

	
	/**
	 * Tower element that are in the inventory of the player (Therefore not yet built)
	 */
	private ArrayList<TowerElement> inventory = new ArrayList<TowerElement>();
	
	
	/**
	 * List of the buying agents cards the player has on his hand
	 */
	private ArrayList<BuyingAgent> buyingAgents = new ArrayList<BuyingAgent>();
	
	
	/**
	 * List of all built towers of the player
	 */
	private ArrayList<Tower> towers = new ArrayList<Tower>();
	
	
	/**
	 * Constructor
	 */
	public Player(IGameBoard gameBoard) throws RemoteException {
		super();
		this.gameBoard = gameBoard;
	}

	
	/**
	 * Setter for player name
	 */
	@Override
	public void setName(String name) throws RemoteException {
		this.name = name;
		gameBoard.reportUpdatePlayerList();
	}

	
	/**
	 * Getter for player name
	 */
	@Override
	public String getName() throws RemoteException {
		return name;
	}

	
	/**
	 * Setter for player color
	 */
	@Override
	public void setColor(int color) throws RemoteException {
		this.color = color;
		gameBoard.reportUpdatePlayerList();
	}

	
	/**
	 * Getter for player color
	 */
	@Override
	public int getColor() throws RemoteException {
		return color;
	}
	
	
	/**
	 * Add prestige points to player's score
	 */
	public void addPoints(int points) {
		this.points += points;
	}
	
	
	/**
	 * Get player's prestige point score
	 */
	@Override
	public int getPoints() throws RemoteException {
		return points;
	}
	
	
	/**
	 * Sets if player is ready to start a new game
	 */
	@Override
	public void setReady(boolean ready) throws RemoteException {
		this.ready = ready;
		gameBoard.reportUpdatePlayerList();
		gameBoard.startGame();
	}

	
	/**
	 * Returns true if player ready to start a new game 
	 */
	@Override
	public boolean isReady() throws RemoteException {
		return ready;
	}
	
	
	/**
	 * Player gets money
	 */
	public void recieveMoney(int amount) {
		money += amount;
	}
	
	
	/**
	 * Player has to give money
	 */
	public void payMoney(int amount) {
		money -= amount;
	}
	
	
	/**
	 * Check if player has enough money to pay amount.
	 */
	public boolean checkMoney(int amount) throws RemoteException {
		return amount <= money;
	}
	
	
	/**
	 * Returns how much money the player has.
	 */
	public int getMoneyBalance() throws RemoteException {
		return money;
	}


	/**
	 * Get array of IDs of buying agent cards on the player's hand.
	 */
	public int[] getBuyingAgentIDs() throws RemoteException {
		int[] ids = new int[buyingAgents.size()];
		for(int i = 0; i < buyingAgents.size(); i++) {
			ids[i] = buyingAgents.get(i).getId();
		}
		return ids;
	}
	
	
	/**
	 * Removes the buying agent card with the given ID.
	 */
	public boolean removeBuyingAgent(int id) {
		for(int i = 0; i < buyingAgents.size(); i++) {
			if(buyingAgents.get(i).getId() == id) {
				buyingAgents.remove(i);
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * Returns array with IDs of all tower elements in the inventory of the player.
	 */
	@Override
	public int[] getInventoryIDs() throws RemoteException {
		int[] ids = new int[inventory.size()];
		for(int i = 0; i < inventory.size(); i++) {
			ids[i] = inventory.get(i).getId();
		}
		return ids;
	}
	
	
	/**
	 * Add an tower element to the player's inventory
	 */
	public void addElementToInventory(TowerElement element) {
		inventory.add(element);
	}
	
	
	/**
	 * Remove tower element with ID from player's inventory.
	 * Returns false, if element isn't in the player's inventory.
	 */
	public boolean removeElementFromInventory(int elementId) {
		for(int i = 0; i < inventory.size(); i++) {
			if(inventory.get(i).getId() == elementId) {
				inventory.remove(i);
				return true;
			}
		}
		return false;
	}
	

	/**
	 * Give player a buying agent card.
	 */
	public void addBuyingAgent(BuyingAgent buyingAgent) {
		buyingAgents.add(buyingAgent);
	}
	
	
	/**
	 * Returns true if player has used all his buying agents.
	 */
	public boolean usedAllBuyingAgents() {
		return buyingAgents.size() == 0;
	}
	
	
	/**
	 * Calculating end of season score for player.
	 */
	public void endOfSeason() {
		for(int i = 0; i < towers.size(); i++) {
			points++;
			points += towers.get(i).getNumOfGolden();
		}
	}
	
	
	/**
	 * Returns array with all towers and the IDs of their elements of the player
	 * "," between tower elements and ";" between towers.
	 * Example: Tower 1 with elements 1, 2, 3 and 4. Tower 2 with elements 5 and 6:
	 * "1,2,3,4;5,6"
	 */
	@Override
	public String getTowerInstructions() throws RemoteException {
		String instructions = "";
		if(towers.size() >= 1) {
			instructions += towers.get(0).getInstructions();
		}
		for(int i = 1; i < towers.size(); i++) {
			// instructions += ";" + (towers.get(i).getInstructions()); SONAR -> critical!
			instructions = instructions.concat(";").concat(towers.get(i).getInstructions());
		}
		return instructions;
	}
	
	
	/**
	 * Returns list with all towers of the player
	 */
	public ArrayList<Tower> getTowers() {
		return towers;
	}
}
